package juc.executors;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ThreadPoolExecutorTask {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = new ThreadPoolExecutor(10, 20, 30, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1), r -> {
            Thread thread = new Thread(r);
            return thread;
        }, new ThreadPoolExecutor.AbortPolicy());

        IntStream.range(0, 20).boxed().forEach(i -> {
            //execute()非阻塞方法
            executorService.execute(() -> {
                timeSleep(2);
                System.out.println(Thread.currentThread().getName() + "->" + i + " finish done.");
                //while (true) {
                //}
            });
        });
        /**
         * shutdown()非阻塞，会被interrupt()标记，在执行的线程会继续执行完成，空闲线程会退出
         * shutdown()将线程池状态置为SHUTDOWN,并不会立即停止,只是关闭了提交通道，用submit()是无效的；而内部该怎么跑还是怎么跑，跑完再停。
         */
        executorService.shutdown();
        /**
         * 当前线程阻塞，直到等所有已提交的任务（包括正在跑的和队列中等待的）执行完。
         * 用于所有线程执行完成之后，执行串行化任务
         * shuntdown()和awaitTermination()要一起使用
         */
        executorService.awaitTermination(1,TimeUnit.HOURS);

        /**
         * 将线程池状态置为STOP。企图立即停止，事实上不一定：
         * 跟shutdown()一样，先停止接收外部提交的任务
         * 忽略队列里等待的任务
         * 尝试将正在跑的任务interrupt中断
         * 返回未执行的任务列表，即blocking queue中的线程
         *
         * 它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的，但是大家知道，这种方法的作用有限，
         * 如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。
         * 所以，ShutdownNow()并不代表线程池就一定立即就能退出，它也可能必须要等待所有正在执行的任务都执行完成了才能退出。
         * 但是大多数时候是能立即退出的
         */
        //List<Runnable> runnableList = null;
        //try {
        //    runnableList = executorService.shutdownNow();
        //} catch (Exception e) {
        //    e.printStackTrace();
        //}
        //System.out.println(runnableList.size());
        System.out.println("====");
    }

    private static void timeSleep(long time) {
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
